"""
2）应用蓝图
"""
from flask_login import login_user, logout_user, current_user, login_required

from app import db
from app.auth import auth
from app.auth.forms import RegisterationForm, LoginForm
from flask import render_template, flash, redirect, url_for, request

from app.auth.send_mail import send_mail
from app.models import User, Role


@auth.route('/')
def index():
    return render_template('auth/index.html')


# 报错解决：Method not Allowed
@auth.route('/register',methods=['POST','GET'])
def register():
    """
    register:
      GET:获取注册页面
      POST:获取注册页面提交的数据信息
        1）判断是否为POST方法提交数据，并且数据是否通过表单验证
        2)如果通过验证，将表单提交的数据存储到数据库中;注册成功，跳转到登陆页面
           获取表单提交的数据有两种方式：
              i、form.data  是一个字典，通过key值获取
              ii、form.email.data   form.username.data
    """
    form=RegisterationForm()
    if form.validate_on_submit():
        user=User()
        user.username=form.username.data
        user.password=form.password.data
        user.email=form.email.data
        #用户角色Role在交互式环境中创建一个普通用户
        #role=Role(name='普通会员')
        #db.session.add(role)
        #db.session.commit()
        user.role=Role.query.filter_by(name='普通用户').first()
        db.session.add(user)
        db.session.commit()
        flash('用户%s注册成功'%(user.username),category='success')
        # 提交数据库之后才能赋予新用户id值，而确认令牌需要用id，所以不能延后提交
        token=user.generate_confirmation_token()
        # 接收人用列表存储
        send_mail(to=[user.email,],
                  subject='请激活你的任务管理平台账号',
                  filename='auth/confirm',
                  user=user,
                  token=token)
        flash('平台验证消息已经发送到你的邮箱，请确认后登录。',category='success')
        #return redirect('/login')
        #url_for('auth.login') 根据视图函数，寻找对应的路由地址
        return redirect(url_for('auth.login'))
    return render_template('auth/register.html',form=form)


@auth.route('/login',methods=['POST','GET'])
def login():
    form=LoginForm()
    if form.validate_on_submit():
        # 判断用户是否存在且用户密码是否正确
        user=User.query.filter_by(email=form.email.data).first()
        if user is not None and user.verity_password(form.password.data):
            login_user(user)
            # 利用login_user函数将登录信息存入session中
            user.ping()   # 更新用户最后一次登录的时间
            flash('用户%s登录成功'%(user.username),category='success')
            return redirect(url_for('todo.list'))
        else:
            flash('用户%s登录失败'%(form.email.data),category='error')#这里用form.email.data是因为登录信息不正确，所以需要从data中获取
            return redirect(url_for('auth.login'))
    return render_template('auth/login.html',form=form)


@auth.route('/logout')
@login_required
#此装饰器是用来判断用户是否已经登录
#当一个函数被多个装饰器装饰时，执行的顺序时从上往下执行，被装饰的顺序是从下往上装饰
#所以这里是先进入logout路由，然后判断是否已经登录，如果已经登录则执行注销
def logout():
    logout_user()
    flash('用户注销成功',category='success')
    return redirect(url_for('auth.index'))


# confirm/ndwefowncsdno
# confirm/ndwefowncsdne
# confirm/ndwefowncsdnw
@auth.route('/confirm/<token>')
@login_required # 用来确认用户是否登录，登录后才能判断当前用户是否验证
def confirm(token):
    """
    1)判断账户是否验证，如果已经验证，跳转到主页
    2）如果没有验证，执行验证函数，更新账户的confirmed值
    """
    if current_user.confirmed:
        return redirect(url_for('todo.list'))
    if current_user.confirm(token):
        flash('验证邮箱通过',category='success')
        return redirect(url_for('todo.list'))
    else:
        flash('验证连接失败',category='error')
        return redirect(url_for('auth.login'))


@auth.before_app_request
def before_request():
    """
    钩子函数：当用户已登录但是邮箱未确认账户，则进入unconfirmed页面
    request.endpoint:指通过蓝图获取的视图函数的名字（auth.login）\
    auth中的register、login、logout以及static静态文件都不会被拦截
    """
    if current_user.is_authenticated \
            and not current_user.confirmed \
            and request.endpoint[:5] != 'auth.' \
            and request.endpoint != 'static.':
        return redirect(url_for('auth.unconfirmed'))


@auth.route('/unconfirmed')
def unconfirmed():
    # 如果当前用户是匿名用户或者已经验证的用户，则访问主页，否则进入未验证页面
    if current_user.is_anonymous or current_user.confirmed:
        return redirect(url_for('todo.list'))
    token=current_user.generate_confirmation_token()
    return render_template('auth/unconfirmed.html')


@auth.route('/reconfirm')
def resend_confirmation():
    token=current_user.generate_confirmation_token()
    try:
        send_mail([current_user.email],'请激活你的任务管理平台账号',
                  'auth/confirm',user=current_user,token=token)
    except Exception as e :
        print(e)
        flash(str(e),category='error')
        return redirect(url_for('auth.register'))
    else:
        flash('新的平台验证消息已经发送到你的邮箱，请确认后登录.',category='success')
        #发送确认邮件给用户，如果没有报错跳转到登录页面重新登录
        return redirect(url_for('auth.login'))

